package fudan.se.project.service.advanced.account;

import fudan.se.project.controller.request.LoginRequest;
import fudan.se.project.controller.request.RegisterRequest;
import fudan.se.project.controller.response.BaseResponse;
import fudan.se.project.controller.response.LoginResponse;
import fudan.se.project.domain.User;
import fudan.se.project.service.infrastructure.entity.UserService;
import fudan.se.project.service.infrastructure.entity.sysrole.SystemAuthorityService;
import fudan.se.project.service.infrastructure.func.account.AccountRegisterService;
import fudan.se.project.util.http.ResponseWrapperUtil;
import fudan.se.project.util.jwt.JwtTokenUtil;
import fudan.se.project.util.user.UserDetailsUtil;
import lombok.Data;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.stereotype.Service;


/**
 * @author X Yang
 */
@Service
@Data
public class AccountService {

    private ResponseWrapperUtil responseWrapperUtil;

    private JwtTokenUtil jwtTokenUtil;

    private UserService userService;

    private SystemAuthorityService systemAuthorityService;

    private AccountRegisterService accountRegisterService;

    private UserDetailsUtil userDetailsUtil;


    @Autowired
    public AccountService(
            ResponseWrapperUtil responseWrapperUtil,
            JwtTokenUtil jwtTokenUtil,
            UserService userService,
            SystemAuthorityService systemAuthorityService,
            AccountRegisterService accountRegisterService,
            UserDetailsUtil userDetailsUtil
    ) {
        this.responseWrapperUtil = responseWrapperUtil;
        this.userService = userService;
        this.jwtTokenUtil = jwtTokenUtil;
        this.accountRegisterService = accountRegisterService;
        this.systemAuthorityService = systemAuthorityService;
        this.userDetailsUtil = userDetailsUtil;

    }

    /**
     * Creates a new user and store it in the database.
     *
     * @param request the request passed from UserAccountController.
     * @return a responseBody wrapped by ResponseWrapperUtil.
     * @see fudan.se.project.util.http.ResponseWrapperUtil#buildResponseBody(Object, HttpStatus)
     */
    public ResponseEntity<?> register(RegisterRequest request) {
        if (userService.findByUsername(request.getUsername()) != null) {
            BaseResponse baseResponse = new BaseResponse("username has been registered");
            return responseWrapperUtil.buildResponseBody(baseResponse, HttpStatus.BAD_REQUEST);
        } else if (userService.findByEmail(request.getEmail()) != null) {
            BaseResponse baseResponse = new BaseResponse("email has been registered");
            return responseWrapperUtil.buildResponseBody(baseResponse, HttpStatus.BAD_REQUEST);
        } else {
            accountRegisterService.process(request.toUser(), request.getPassword());

            BaseResponse baseResponse = new BaseResponse("register success");
            return responseWrapperUtil.buildResponseBody(baseResponse, HttpStatus.OK);
        }
    }

    /**
     * Lets a user log in and send token to its client.
     *
     * @param request the request passed from UserAccountController.
     * @return a responseBody wrapped by ResponseWrapperUtil.
     * @see fudan.se.project.util.http.ResponseWrapperUtil#buildResponseBody(Object, HttpStatus)
     */
    public ResponseEntity<?> login(LoginRequest request) {

        User user = userService.findByUsername(request.getUsername());

        if (user == null) {
            BaseResponse baseResponse = new BaseResponse("username not found");
            return responseWrapperUtil.buildResponseBody(baseResponse, HttpStatus.NOT_FOUND);
        } else {

            if (!userService.isCorrectPassword(user, request.getPassword())) {

                BaseResponse baseResponse = new BaseResponse("password mismatch");
                return responseWrapperUtil.buildResponseBody(baseResponse, HttpStatus.UNAUTHORIZED);

            } else {

                String token = jwtTokenUtil.generateToken(user);
                LoginResponse response = new LoginResponse(token, user);
                response.setMessage("login success");
                return responseWrapperUtil.buildResponseBody(response, HttpStatus.OK);

            }
        }
    }

    public ResponseEntity<?> update() {
        User currentUser = userDetailsUtil.currentUser();
        String token = jwtTokenUtil.generateToken(currentUser);
        LoginResponse response = new LoginResponse(token, currentUser);
        response.setMessage("success");
        return responseWrapperUtil.buildResponseBody(response, HttpStatus.OK);
    }
}
